﻿#include "xstaticchart_p.h"
#include <algorithm>
#include <typeinfo>

#include "structdata.h"
#include "basedata.h"
#include "objlib.h"

using namespace xvs;

XStaticChartPrivate::XStaticChartPrivate()
    : tickLabelType(Default_TickLabel),
      xRange(QCPRange(0, 10)),
      yRange(QCPRange()),
      tickLabelsCount(0)
{

}

/*!
 * \brief XStaticChartPrivate::ArrayJudge
 * \param array
 * \param countJudge(0: 不判断数量，其他: 判断数量，默认: 0)
 * \return
 */
template<typename T>
bool XStaticChartPrivate::ArrayJudge(Array &array, int countJudge)
{
    //数组为空直接返回
    if(!array.Count())
        return false;

    //获取目标类型
    QString targetType = typeid(T).name();

    //判断数组类型
    typeName = array.ItemType();

    if("double" == targetType)
    {
        if ("Integer" != typeName && "Real" != typeName)
        {
            typeName = "";
            return false;
        }
    }
    else if("QString" == targetType)
    {
        if ("String" != typeName)
        {
            typeName = "";
            return false;
        }
    }
    else if("QColor" == targetType)
    {
        if("Point3D" != typeName)
        {
            typeName = "";
            return false;
        }
    }

    if(!countJudge)
        return true;

    //判断数组容量
    if(countJudge != array.Count())
    {
        typeName = "";
        return false;
    }

    return true;
}

/*!
 * \brief XStaticChartPrivate::ArrayToQCPRange
 * \param array
 * \param range
 * \note  传入的array需满足ArrayJudge的判断，
 */
template<typename T>
void XStaticChartPrivate::ArrayToQCPRange(Array &array, QCPRange &range)
{
    double arrayFirst = array.At<T>(0).Value();
    double arraySecond = array.At<T>(1).Value();

    range.lower = qMin(arrayFirst, arraySecond);
    range.upper = qMax(arrayFirst, arraySecond);
}

/*!
 * \brief XStaticChartPrivate::ArrayToQVector
 * \param array
 * \param vector
 */
template<typename T1, typename T2>
QVector<T2> XStaticChartPrivate::ArrayToQVector(Array &array)
{
    QVector<T2> vector;
    for(int i = 0; i < array.Count(); ++i)
    {
        vector << array.At<T1>(i).Value();
    }
    return vector;
}

XStaticChartPrivate::~XStaticChartPrivate()
{

}

XStaticChart::XStaticChart(QWidget *parent)
    : QCustomPlot(parent),
      barCharts(new XCustomBars(this)),
      pointLineCharts(new XCustomPointLines(this)),
      XStaticChartP(new XStaticChartPrivate)
{
    //设置渐变背景
    QLinearGradient plotGradient;
    plotGradient.setStart(0, 0);
    plotGradient.setFinalStop(0, 300);
    plotGradient.setColorAt(0, QColor(0,220,255));
    plotGradient.setColorAt(1, QColor(30,30,30));
    this->setBackground(plotGradient);

    //设置图
    setupChart();
}

XStaticChart::~XStaticChart()
{
}

/*!
 * \brief XStaticChart::getXArray
 * \return
 */
Array XStaticChart::getXArray() const
{
    return XStaticChartP->xArray;
}

/*!
 * \brief XStaticChart::setXArray
 * \param array
 */
void XStaticChart::setXArray(Array &array)
{
    //先判断合法性
    if(!XStaticChartP->ArrayJudge<double>(array))
        return;

    //将Array转换为QVector
    if("Integer" == XStaticChartP->typeName)
        XStaticChartP->x = XStaticChartP->ArrayToQVector<Integer, double>(array);
    else
        XStaticChartP->x = XStaticChartP->ArrayToQVector<Real, double>(array);

    //重新设置图
    setupChart();

    //更新数据
    XStaticChartP->xArray.Clear();
    XStaticChartP->xArray = array;
}

/*!
    \property XStaticChart::xRangeArray
    \brief the rangeArray of the xAxis

    The default xRangeArray is (0, 10).

    \sa indent
*/
Array XStaticChart::getXRangeArray() const
{
    return XStaticChartP->xRangeArray;
}

void XStaticChart::setXRangeArray(Array &array)
{
    //先判断合法性
    if(!XStaticChartP->ArrayJudge<double>(array, 2))
        return;

    //将Array转换为QCPRange
    if("Integer" == XStaticChartP->typeName)
        XStaticChartP->ArrayToQCPRange<Integer>(array, XStaticChartP->xRange);
    else
        XStaticChartP->ArrayToQCPRange<Real>(array, XStaticChartP->xRange);

    //重新设置图
    setupChart();

    //更新数据
    XStaticChartP->xRangeArray.Clear();
    XStaticChartP->xRangeArray = array;
}

/*!
    \property XStaticChart::yRangeArray
    \brief the rangeArray of the yAxis.

    \sa indent
*/
Array XStaticChart::getYRangeArray() const
{
    return XStaticChartP->yRangeArray;
}

void XStaticChart::setYRangeArray(Array &array)
{
    //先判断合法性
    if(!XStaticChartP->ArrayJudge<double>(array, 2))
        return;

    if("Integer" == XStaticChartP->typeName)
        XStaticChartP->ArrayToQCPRange<Integer>(array, XStaticChartP->yRange);
    else
        XStaticChartP->ArrayToQCPRange<Real>(array, XStaticChartP->yRange);

    //重新设置图
    setupChart();

    //更新数据
    XStaticChartP->yRangeArray.Clear();
    XStaticChartP->yRangeArray = array;
}

/*!
    \property XStaticChart::tickLabelType
    \brief the type of the tickLabel

    The default tickLabelType is Default_TickLabel.

    \sa indent
*/
ChartTickLabelType XStaticChart::getTickLabelType() const
{
    return XStaticChartP->tickLabelType;
}

void XStaticChart::setTickLabelType(ChartTickLabelType type)
{
qDebug() << "设置类型： " << type;
    if(XStaticChartP->tickLabelType == type)
        return;

    XStaticChartP->tickLabelType = type;
    //重新设置图
    setupChart();
}

/*!
 * \brief XStaticChart::setTickLabel
 * \param array
 */
void XStaticChart::setTickLabel(Array &array)
{
qDebug() << "--------------setTickLabel";
    //先判断合法性
    if(!XStaticChartP->ArrayJudge<QString>(array))
        return;

    //计算数据数量
    XStaticChartP->tickLabelsCount = array.Count();

    //将Array转换为QVector
    XStaticChartP->tickLabels = XStaticChartP->ArrayToQVector<String, QString>(array);

    //重新设置图
    setupChart();
}


/*!
 * \brief XStaticChart::setupChart
 */
void XStaticChart::setupChart()
{
qDebug() << "-------------------------设置Chart： " << XStaticChartP->tickLabelType;
    //清除先前的图
int plottableCount = this->plottableCount();
if (plottableCount != 0)
    this->clearPlottables();

    //设置坐标轴
    setupAxis();

    //设置图像移动控制
    this->setInteractions(QCP::iRangeDrag | QCP::iSelectPlottables | QCP::iRangeZoom);

qDebug() << "马上绘制";
    //绘制
    this->replot();
qDebug() << "绘制完毕";
}

/*!
 * \brief XStaticChart::setupAxis
 */
void XStaticChart::setupAxis()
{
qDebug() << "--------------setupAxis";
    // prepare x axis
    //生成自然数横坐标
//    XStaticChartP->x.clear();
//    for (int i = 3; i <= XStaticChartP->dataCount + 2; ++i)
//        XStaticChartP->x << i;

//    //测试证明横坐标支持小数
//    XStaticChartP->x << 1.1 << 2.2 << 3.3 << 4.4 << 5.5 << 6.6
//                     << 7.7 << 8.8 << 9.9 << 11;
    //设置自然数标签或者自定义字符串标签
    if(Default_TickLabel == XStaticChartP->tickLabelType)
    {
        QSharedPointer<QCPAxisTickerFixed> fixedTicker(new QCPAxisTickerFixed);
        this->xAxis->setTicker(fixedTicker);
        fixedTicker->setTickStep(1.0);
        fixedTicker->setScaleStrategy(QCPAxisTickerFixed::ssMultiples);
    }
    else if(Custom_TickLabel == XStaticChartP->tickLabelType)
    {
        QSharedPointer<QCPAxisTickerText> textTicker(new QCPAxisTickerText);
        textTicker->setTicks(XStaticChartP->x, XStaticChartP->tickLabels);
        this->xAxis->setTicker(textTicker);
    }
    //设置x坐标轴末尾形状
    this->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);

    // prepare y axis
    //设置y轴末端箭头
    this->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);

    //设置坐标轴拖动策略
    this->axisRect()->setRangeDrag(Qt::Horizontal);

    //设置缩放仅限x轴
    QList<QCPAxis*> axes;
    axes << this->xAxis;
    this->axisRect()->setRangeZoomAxes(axes);
}

